package serv

import (
	"context"
	"encoding/base64"
	"errors"
	"time"

	"code.bydev.io/cht/customer/kyc-stub.git/pkg/bybit/kyc/admin/v1"
	"code.bydev.io/cht/customer/kyc_admin_service/internal/pkg/biz"
	"code.bydev.io/cht/customer/kyc_admin_service/internal/pkg/biz/controllers/adminctl"
	"code.bydev.io/cht/customer/kyc_admin_service/internal/pkg/kycadminapi/actionsvc"
	"code.bydev.io/frameworks/byone/core/logc"
	pb "git.bybit.com/svc/stub/pkg/pb/api/kycadmin"
)

type service struct {
	env *biz.Environment
	pb.UnimplementedKycAdminInnerServiceServer
}

func NewService(env *biz.Environment) *service {
	return &service{env: env}
}

func (s service) GetKycActionList(ctx context.Context, req *pb.GetKycActionListRequest) (*pb.GetKycActionListResponse, error) {
	h := s.env.CreateHandlerWithTimeout(ctx, "GetKycActionList", 8*time.Second)
	defer h.Dispose()
	logc.Infow(ctx, "GetKycActionList request", logc.Field("req", req))
	resp, err := adminctl.New(h).GetKycActionList(ctx, req)
	if err != nil {
		logc.Errorw(ctx, "adminctl.New(h).GetKycActionList error", logc.Field("err", err))
		return nil, err
	}
	logc.Infow(ctx, "GetKycActionList resp", logc.Field("resp", resp))
	return resp, err
}

func (s service) GetKycActionDetail(ctx context.Context, req *pb.GetKycActionDetailRequest) (*pb.KycActionDetailResponse, error) {
	h := s.env.CreateHandlerWithTimeout(ctx, "GetKycActionDetail", 4*time.Second)
	defer h.Dispose()
	logc.Infow(ctx, "GetKycActionDetail request", logc.Field("req", req))
	resp, err := adminctl.New(h).GetKycActionDetail(ctx, req)
	if err != nil {
		logc.Errorw(ctx, "adminctl.New(h).GetKycActionDetail error", logc.Field("err", err))
		return nil, err
	}
	logc.Infow(ctx, "GetKycActionDetail resp", logc.Field("resp", resp))
	return resp, err
}

func (s service) AppendLevel2Data(ctx context.Context, req *pb.AppendLevel2DataRequest) (*pb.AppendLevel2DataResponse, error) {
	return &pb.AppendLevel2DataResponse{
		Result: true,
	}, nil
}

func (s service) GetCountryConfig(ctx context.Context, req *v1.GetCountryConfigRequest) (*v1.GetCountryConfigResponse, error) {
	h := s.env.CreateHandlerWithTimeout(ctx, "GetCountryConfig", 3*time.Second)
	defer h.Dispose()
	logc.Infow(ctx, "GetCountryConfig request", logc.Field("req", req))
	resp, err := adminctl.New(h).GetCountryConfig(ctx, req)
	if err != nil {
		logc.Errorw(ctx, "adminctl.New(h).GetCountryConfig error", logc.Field("err", err))
		return nil, err
	}
	logc.Infow(ctx, "GetCountryConfig resp", logc.Field("resp", resp))
	return resp, err
}

func (s service) SetCountryConfig(ctx context.Context, req *v1.SetCountryConfigRequest) (*v1.SetCountryConfigResponse, error) {
	h := s.env.CreateHandlerWithTimeout(ctx, "SetCountryConfig", 3*time.Second)
	defer h.Dispose()
	logc.Infow(ctx, "SetCountryConfig request", logc.Field("req", req))
	resp, err := adminctl.New(h).SetCountryConfig(ctx, req)
	if err != nil {
		logc.Errorw(ctx, "adminctl.New(h).SetCountryConfig error", logc.Field("err", err))
		return nil, err
	}
	logc.Infow(ctx, "SetCountryConfig resp", logc.Field("resp", resp))
	return resp, err
}

func (s service) GetCommonConfig(ctx context.Context, req *v1.GetCommonConfigRequest) (*v1.GetCommonConfigResponse, error) {
	h := s.env.CreateHandlerWithTimeout(ctx, "GetCommonConfig", 3*time.Second)
	defer h.Dispose()
	logc.Infow(ctx, "GetCommonConfig request", logc.Field("req", req))
	resp, err := adminctl.New(h).GetCommonConfig(ctx, req)
	if err != nil {
		logc.Errorw(ctx, "adminctl.New(h).GetCommonConfig error", logc.Field("err", err))
		return nil, err
	}
	logc.Infow(ctx, "GetCommonConfig resp", logc.Field("resp", resp))
	return resp, err
}

func (s service) SetCommonConfig(ctx context.Context, req *v1.SetCommonConfigRequest) (*v1.SetCommonConfigResponse, error) {
	h := s.env.CreateHandlerWithTimeout(ctx, "SetCommonConfig", 3*time.Second)
	defer h.Dispose()
	logc.Infow(ctx, "SetCommonConfig request", logc.Field("req", req))
	resp, err := adminctl.New(h).SetCommonConfig(ctx, req)
	if err != nil {
		logc.Errorw(ctx, "adminctl.New(h).SetCommonConfig error", logc.Field("err", err))
		return nil, err
	}
	logc.Infow(ctx, "SetCommonConfig resp", logc.Field("resp", resp))
	return resp, err
}

func (s service) GetKycImage(ctx context.Context, req *v1.GetKycImageReq) (*v1.GetKycImageResp, error) {
	logc.Infow(ctx, "GetKycImage request", logc.Field("req", req))
	h := s.env.CreateHandlerWithTimeout(ctx, "GetKycImage", 5*time.Second)
	defer h.Dispose()

	tokenBt, err := base64.RawStdEncoding.DecodeString(req.GetToken())
	if err != nil {
		logc.Warnw(ctx, "base64.RawStdEncoding.DecodeString error", logc.Field("err", err))
		return nil, err
	}
	token := string(tokenBt)
	if token == "" {
		logc.Warnw(ctx, "token empty")
		return nil, errors.New("token empty")
	}
	logc.Infow(ctx, "image token info", logc.Field("token", token))
	actionSvc := actionsvc.New(h.KycAdminRepo(), h.SecHub(), h.Logger(), h.Teller())
	imgBody, size, err := actionSvc.GetActionImage(ctx, token)
	if err != nil {
		logc.Errorw(ctx, "actionSvc.GetActionImage error", logc.Field("err", err))
		return nil, err
	}
	if imgBody == nil || size == 0 {
		logc.Warnw(ctx, "image not found")
		return &v1.GetKycImageResp{}, nil
	}
	resp := &v1.GetKycImageResp{
		ImageData: imgBody,
		ImageSize: int64(size),
	}
	logc.Infow(ctx, "GetKycImage resp", logc.Field("size", size))
	return resp, nil
}
